﻿using System;
using System.Collections.Generic;
using System.Reflection;

using zijian666.Converts.Abstractions;
using zijian666.Converts.Core;

namespace zijian666.Converts.Dynamic;

/// <summary>
/// 基于系统原始类型的动态类型
/// </summary>
internal class DynamicPrimitive : DynamicObjectBase<object>
{

    public static readonly DynamicPrimitive Null = new(null, Converts.Settings);

    public DynamicPrimitive(object? value, IConvertSettings convertSettings)
        : base(value, convertSettings)
    {
    }

    public override IEnumerable<string> GetDynamicMemberNames() => Array.Empty<string>();

    protected override object? this[string name]
    {
        get
        {
            const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
            var p = Value?.GetType().GetProperty(name, flags);
            if (p is null)
            {
                return null;
            }
            var getter = ConvertSettings.ReflectCompiler?.CompileGetter<object>(p) ?? p.GetValue;
            if (getter is null)
            {
                return null;
            }
            return getter(Value);
        }
        set
        {
            const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
            var p = Value?.GetType().GetProperty(name, flags);
            if (p is null)
            {
                return;
            }

            var setter = ConvertSettings.ReflectCompiler?.CompileSetter<object>(p) ?? p.SetValue;
            if (setter is null)
            {
                return;
            }
            if (!p.PropertyType.IsInstanceOfType(value))
            {
                value = value.Convert(p.PropertyType, ConvertSettings).Value;
            }
#pragma warning disable CS8604
            setter(Value, value);
#pragma warning restore CS8604
        }
    }
}
